#include "Input.h"
#include "Waiting.h"
#include "Global.h"
#include "StringTable.h"
#include "UserPortRS232.h"
#include "Output.h"
#include "Session.h"
#include "Twist.h"
#include "Chat.h"

#include <string.h>
#include <conio.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>

#ifdef __CBM__
#include <cbm.h>
#elif defined(__APPLE2ENH__)
#include <apple2enh.h>
#elif defined(__ATARI__)
#include <atari.h>
#endif

void pause(encoding_t encoding, outDirections_t outDirection)
{
	static bool dcdStart;
	static connect_states_t originalState;
	static time_t startTime;

	startTime = time(NULL);

	originalState = _connectState;
	
	dcdStart = readDCD();

	outputString(encoding, outDirection, INPUT_PAUSE_1);

	while((outDirection & OD_SCREEN && !kbhit()) &&
		(outDirection & OD_MODEM && readByteRS232() == 0)
		&& (dcdStart == readDCD())
		&& originalState == _connectState
		&& time(NULL) - startTime < 120);

	if(outDirection & OD_SCREEN && kbhit()) cgetc();

	if(time(NULL) - startTime >= 120)
	{
		_connectState = CS_DISCONNECTED;
		return;
	}

	outputString(encoding, outDirection, INPUT_PAUSE_2);

	_connectState = readDCD() ? CS_CONNECTED : CS_DISCONNECTED;
}

char getYesNo(void)
{
	static char c;

	c = 0;
	while(c == 0)
	{
		if(kbhit())
		{
			switch(cgetc())
			{
			case 'y': case 'Y':
				c = 1;
				break;
			case 'n': case 'N':
				c = 2;
				break;
			}
		}
	}

	return c;
}

bool savail()
{
	return true;
}

char sgetc()
{
	static char c;

	c = readByteRS232();

	if(_currentSession.sessionEncoding == EN_ASCII) c = twistCharAtoP(c);

	return c;
}

char inputChar(encoding_t encoding, outDirections_t outdirection, inputOptions_t options)
{
	static char c, k;
	static bool dcdStart;
	static time_t startTime;

	startTime = time(NULL);

	dcdStart = readDCD();

	k = c = 0;

	while(c == 0)
	{
		if(readDCD() != dcdStart ||  time(NULL) - startTime >= 120)
		{
			_connectState = CS_DISCONNECTED;
			return 0;
		}

		if(outdirection & OD_MODEM && savail())
		{
			k = sgetc();
		}

		if(c == '\0' && outdirection & OD_SCREEN && kbhit())
		{
			k = cgetc();
			if(k == CH_F7)
			{
				enterChat(outdirection);
			}
		}

		if((options & IO_NUMERIC || 
			options & IO_ALPHA_NUMERIC || 
			options & IO_ANY_CHARACTER) && 
			(k >= '0' && k <= '9' ))
		{
			c = k;
		}
		else if((options & IO_ALPHA ||
			options & IO_ALPHA_NUMERIC ||
			options & IO_ANY_CHARACTER) &&
			((k >= 'a' && k <= 'z') || 
			(k >= 'A' && k <= 'Z' ) || 
			(k >= 0x21 && k <= 0x2F) ||
			(k >= 0x3A && k <= 0x3F) ||
			(k >= 0x5B && k <= 0x5F) ||
			k == ' ' ))
		{
			c = k;
		}
		else if(options & IO_ANY_CHARACTER &&
			k != CH_DEL && k != CH_ENTER)
		{
			c = k;
		}
		
		if(options & IO_ENTER && k == CH_ENTER)
		{
			c = k;
		}
	}

	return c;
}

char * input(encoding_t encoding, outDirections_t outdirection, inputOptions_t options, char *outbuffer, char length, bool mask)
{
	static char c, i;
	bool paint;
	char x, y;
	static bool dcdStart;
	static time_t startTime;

	startTime = time(NULL);

	dcdStart = readDCD();

	x = wherex();
	y = wherey();

	c = '\0';
	memset(outbuffer, 0, length + 1);

	if(outdirection & OD_MODEM)
	{
		// out _ to modem
	}

	if(outdirection & OD_SCREEN)
	{
		cputc(CH_UNDERLINE);
	}

	c = '\0';
	while(c != CH_ENTER) 
	{
		if(readDCD() != dcdStart || time(NULL) - startTime >= 120)
		{
			_connectState = CS_DISCONNECTED;
			break;
		}

		c = '\0';
		paint = false;

		if(outdirection & OD_MODEM && savail())
		{
			c = sgetc();
		}

		if(c == '\0' && outdirection & OD_SCREEN && kbhit())
		{
			c = cgetc();
			if(c == CH_F7)
			{
				enterChat(outdirection);
			}
		}

		if(c != CH_ENTER && c != '\0')
		{

			if((options & IO_NUMERIC || 
				options & IO_ALPHA_NUMERIC || 
				options & IO_ANY_CHARACTER) && 
				strlen(outbuffer) < length &&
				(c >= '0' && c <= '9' ))
			{
				outbuffer[strlen(outbuffer)] = c;
				paint = true;
			}
			else if((options & IO_ALPHA ||
				options & IO_ALPHA_NUMERIC ||
				options & IO_ANY_CHARACTER) &&
				strlen(outbuffer) < length &&
				((c >= 'a' && c <= 'z') || 
				(c >= 'A' && c <= 'Z' ) || 
				(c >= 0x21 && c <= 0x2F) ||
				(c >= 0x5b && c <= 0x5F) ||
				c == ' '))
			{
				outbuffer[strlen(outbuffer)] = c;
				paint = true;
			}
			else if(options & IO_ANY_CHARACTER &&
				strlen(outbuffer) < length &&
				c != CH_DEL && c != CH_ENTER)
			{
				outbuffer[strlen(outbuffer)] = c;
				paint = true;
			}
			else if(c == CH_DEL)
			{
				//cputcxy(x + strlen(outBuffer), y, ' ');
				if(strlen(outbuffer) > 0)
				{
					outbuffer[strlen(outbuffer) - 1] = '\0';
					paint = true;
				}
			}

			if(c != '\0' && c != CH_ENTER)
			{
				if(c != CH_DEL)
				{
					if(outdirection & OD_MODEM)
					{
						if(paint)
						{
							if(mask)
							{
								outputCharacter(PLATFORM_ENCODING, OD_MODEM, '*');
							}
							else
							{
								outputCharacter(PLATFORM_ENCODING, OD_MODEM, c);
							}
						}
					}

					if(outdirection & OD_SCREEN)
					{
						if(paint)
						{
							if(mask)
							{
								gotoxy(x, y);
								for(i = 0; i<strlen(outbuffer); ++i) cputc('*');
							}
							else
							{
								cputsxy(x, y, outbuffer);
							}
							cputc(CH_UNDERLINE);
						}
					}
				}
				else
				{
					if(outdirection & OD_MODEM && paint && strlen(outbuffer) >= 0)
					{
						if(_currentSession.sessionEncoding == EN_ASCII)
						{
							outputCharacter(PLATFORM_ENCODING, OD_MODEM, 8);
							outputCharacter(PLATFORM_ENCODING, OD_MODEM, ' ');
							outputCharacter(PLATFORM_ENCODING, OD_MODEM, 8);
						}
						else
						{
							outputCharacter(PLATFORM_ENCODING, OD_MODEM, c);
						}
					}

					if(outdirection & OD_SCREEN)
					{
						if(paint)
						{
							if(mask)
							{
								gotoxy(x, y);
								for(i = 0; i<strlen(outbuffer); ++i) cputc('*');
							}
							else
							{
								cputsxy(x, y, outbuffer);
							}
							cputc(CH_UNDERLINE);
							cputc(CH_SPACE);
						}
					}
				}
			}
		}
	}

	if(outdirection & OD_SCREEN)
	{
		cputcxy(x + strlen(outbuffer), y, CH_SPACE);
	}
	// do same for modem

	return outbuffer;
}

char * inputString(inputOptions_t options, char* outbuffer, char length, bool mask)
{
	static char c;
	static bool paint;
	static char x, y;

	x = wherex();
	y = wherey();

	textcolor(COLOR_GRAY3);
	revers(true);
	for(c = 0; c <= length; ++c)
	{
		cputc(' ');
	}
	revers(false);

	if(strlen(outbuffer) > 0)
	{
		textcolor(COLOR_WHITE);
		if(!mask)
		{
			cputsxy(x, y, outbuffer);
		}
		else
		{
			for(c = 0; c < strlen(outbuffer); ++c)
			{
				cputcxy(x + c, y, '*');
			}
		}
		cputc(CH_UNDERLINE);
	}
	else
	{
		memset(outbuffer, 0, length + 1);
		textcolor(COLOR_WHITE);
		cputcxy(x, y, CH_UNDERLINE);
	}

	c = 0;

	while(c != CH_ENTER)
	{
		if(kbhit())
		{
			c = cgetc();

			if(c != CH_ENTER)
			{
				paint = false;

				if((options & IO_NUMERIC || 
					options & IO_ALPHA_NUMERIC || 
					options & IO_ANY_CHARACTER) && 
					strlen(outbuffer) < length &&
					(c >= '0' && c <= '9' ))
				{
					outbuffer[strlen(outbuffer)] = c;
					paint = true;
				}
				else if((options & IO_ALPHA ||
					options & IO_ALPHA_NUMERIC ||
					options & IO_ANY_CHARACTER) &&
					strlen(outbuffer) < length &&
					((c >= 'a' && c <= 'z') || 
					(c >= 'A' && c <= 'Z' ) || 
					(c >= 0x21 && c <= 0x2F) ||
					(c >= 0x5b && c <= 0x5F) ||
					c == ' '))
				{
					outbuffer[strlen(outbuffer)] = c;
					paint = true;
				}
				else if(options & IO_ANY_CHARACTER &&
					strlen(outbuffer) < length &&
					c != CH_DEL && c != CH_ENTER)
				{
					outbuffer[strlen(outbuffer)] = c;
					paint = true;
				}
				else if(c == CH_DEL)
				{
					//cputcxy(x + strlen(outBuffer), y, ' ');
					outbuffer[strlen(outbuffer) - 1] = '\0';
					paint = true;
				}

				if(paint)
				{
					gotoxy(x, y);
					textcolor(COLOR_GRAY3);
					revers(true);
					for(c = 0; c <= length; ++c)
					{
						cputc(' ');
					}
					revers(false);

					textcolor(COLOR_WHITE);
					if(!mask)
					{
						cputsxy(x, y, outbuffer);
					}
					else
					{
						for(c = 0; c < strlen(outbuffer); ++c)
						{
							cputcxy(x + c, y, '*');
						}
					}
					cputc(CH_UNDERLINE);
				}
				c = 0;
			}
		}
	}

	return outbuffer;
}